package com.comment.util.pay;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 等级池
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LevelMapping {
    private static final Logger log = LoggerFactory.getLogger(LevelMapping.class);
    private BigDecimal pool = BigDecimal.ZERO;
    private Map<Integer, LevelPool> levelPool = new HashMap<>();

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class LevelUp {
        private Integer targetLevel;
        private BigDecimal upNeed;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class LevelPool {
        private Integer targetLevel;
        private BigDecimal startPool;
        private BigDecimal endPool;
        private BigDecimal upThisNeed;
    }


    public void addPool(LevelUp levelUp) {
        Set<Integer> levelPoolKeys = this.levelPool.keySet();
        int maxKey = levelPoolKeys.stream().mapToInt(Integer::intValue).max().orElse(0);
        int next = maxKey + 1;

        if (next == levelUp.targetLevel) {
            this.pool = this.pool.add(levelUp.upNeed);

            // 新的等级
            LevelPool levelPool = new LevelPool();
            levelPool.setTargetLevel(levelUp.targetLevel);
            levelPool.setStartPool(this.pool);
            levelPool.setUpThisNeed(levelUp.upNeed);
            this.levelPool.put(levelUp.targetLevel, levelPool);
            // 更新旧的等级
            LevelPool maxPool = this.levelPool.get(maxKey);
            if (maxPool != null) {
                maxPool.setEndPool(this.pool);
                this.levelPool.put(maxKey, maxPool);
            }
        } else {
            log.error("当前等级池只能添加的等级为:{}", levelUp.targetLevel);
        }
    }

    public void update(LevelUp levelUp) {
        Set<Integer> levelPoolKeys = this.levelPool.keySet();

        if (levelPoolKeys.contains(levelUp.getTargetLevel())) {
            BigDecimal upThisNeed = this.levelPool.get(levelUp.getTargetLevel()).getUpThisNeed();
            BigDecimal upNeed = levelUp.getUpNeed();

            BigDecimal updateValue = upNeed.subtract(upThisNeed);
            this.pool = this.pool.add(updateValue);

            this.levelPool = this.levelPool.values().stream()
                    .peek(levelPool1 -> {
                        Integer targetLevel = levelPool1.getTargetLevel();
                        Integer updateLevel = levelUp.getTargetLevel();
                        if (targetLevel > updateLevel) {
                            levelPool1.setStartPool(levelPool1.getStartPool().add(updateValue));
                            levelPool1.setEndPool(levelPool1.getEndPool().add(updateValue));
                        }
                        if (targetLevel.equals(updateLevel)) {
                            levelPool1.setEndPool(levelPool1.getEndPool().add(updateValue));
                        }
                    }).collect(Collectors.toMap(LevelPool::getTargetLevel, v -> v));
        } else {
            log.error("当前等级池不包含:{}", levelUp.getTargetLevel());
        }
    }

    public Integer select(BigDecimal value) {
        Collection<LevelPool> values = this.levelPool.values();
        return values.stream()
                .filter(levelPool ->  value.compareTo(levelPool.getStartPool()) >= 0 && value.compareTo(levelPool.getEndPool()) <= 0)
                .map(LevelPool::getTargetLevel)
                .findFirst()
                .orElse(null);
    }

    public Integer select(Integer targetLevel) {
        return this.levelPool.get(targetLevel) == null ? null : this.levelPool.get(targetLevel).getTargetLevel();
    }
}
